package com.youdoneed.user.authority;

import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLUpdateClause;
import com.youdoneed.base.application.AppException;
import com.youdoneed.base.common.GlobalIdWorker;
import com.youdoneed.base.pagination.Page;
import com.youdoneed.base.pagination.Paging;
import com.youdoneed.user.application.QueryHelper;
import com.youdoneed.user.model.Authority;
import com.youdoneed.user.query.QAuthority;
import com.youdoneed.user.query.QRoleAuthority;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 权限管理服务实现类
 *
 * @author Ewing
 * @date 2017.2.8
 */
@Service
@Transactional
public class AuthorityServiceImpl implements AuthorityService {

    @Autowired
    private SQLQueryFactory queryFactory;
    private QAuthority qAuthority = QAuthority.Authority;
    private QRoleAuthority qRoleAuthority = QRoleAuthority.RoleAuthority;

    @Override
    public Authority findAuthorityById(String id) {
        if (!StringUtils.hasText(id)) {
            throw new AppException("权限ID不能为空！");
        }
        return queryFactory.selectFrom(qAuthority)
                .where(qAuthority.authorityId.eq(id))
                .fetchOne();
    }

    @Override
    public Authority addAuthority(Authority authority) {
        if (null == authority) {
            throw new AppException("权限不能为空！");
        }
        if (!StringUtils.hasText(authority.getName())) {
            throw new AppException("权限名不能为空！");
        }
        if (!StringUtils.hasText(authority.getCode())) {
            throw new AppException("权限码不能为空！");
        }

        if (queryFactory.selectFrom(qAuthority)
                .where(qAuthority.code.eq(authority.getCode()))
                .fetchCount() > 0) {
            throw new AppException("当前权限编码已存在！");
        }

        if (StringUtils.hasText(authority.getSuperId())) {
            Authority supAuthority = findAuthorityById(authority.getSuperId());
            if (null == supAuthority) {
                throw new AppException("父权限不存在或已删除！");
            }
            // 限制权限只能为二级
            if (StringUtils.hasText(supAuthority.getSuperId())) {
                throw new AppException("父权限必须是一级权限！");
            }
        } else {
            authority.setSuperId(null);
        }

        authority.setAuthorityId(GlobalIdWorker.nextString());
        authority.setCreateTime(new Date());

        // 如果排序为空，则排在最后
        if (authority.getSorter() == null) {
            Integer sorter = queryFactory.select(qAuthority.sorter.max())
                    .from(qAuthority)
                    .fetchOne();
            authority.setSorter(sorter == null ? 1 : sorter + 1);
            queryFactory.insert(qAuthority)
                    .populate(authority)
                    .execute();
        } else {
            // 找出平级的权限
            List<Authority> authorities;
            if (StringUtils.hasText(authority.getSuperId())) {
                authorities = getSubAuthority(authority.getSuperId());
            } else {
                authorities = getParentAuthority();
            }
            // 添加到第一位
            authorities.add(0, authority);
            queryFactory.insert(qAuthority)
                    .populate(authority)
                    .execute();
            // 重新排序并更新
            authorities.sort(Comparator.comparing(Authority::getSorter));
            int sorter = 1;
            SQLUpdateClause update = queryFactory.update(qAuthority);
            for (Authority auth : authorities) {
                update.set(qAuthority.sorter, sorter++)
                        .where(qAuthority.authorityId.eq(auth.getAuthorityId()))
                        .addBatch();
            }
            update.execute();
        }
        return authority;
    }

    @Override
    public void deleteAuthority(String authorityId) {
        if (!StringUtils.hasText(authorityId)) {
            throw new AppException("请选择要删除记录！");
        }
        // 删除角色权限关联
        queryFactory.delete(qRoleAuthority)
                .where(qRoleAuthority.authorityId.eq(authorityId))
                .execute();
        // 再删除权限
        queryFactory.delete(qAuthority)
                .where(qAuthority.authorityId.eq(authorityId))
                .execute();
    }

    @Override
    public Authority updateAuthority(Authority authority) {
        if (authority == null || !StringUtils.hasText(authority.getAuthorityId())) {
            throw new AppException("请选择要更新的记录！");
        }

        Authority oldAuthority = findAuthorityById(authority.getAuthorityId());
        if (null == oldAuthority) {
            throw new AppException("该权限不存在或已删除！");
        }

        if (StringUtils.hasText(authority.getSuperId())
                && authority.getSuperId().equals(authority.getAuthorityId())) {
            throw new AppException("父权限不能够是自身！");
        }

        if (queryFactory.selectFrom(qAuthority)
                .where(qAuthority.code.eq(authority.getCode()))
                .fetchCount() > 0
                && !oldAuthority.getCode().equals(authority.getCode())) {
            throw new AppException("当前权限编码已存在！");
        }

        if (StringUtils.hasText(authority.getSuperId())) {
            Authority supAuthority = findAuthorityById(authority.getSuperId());
            if (null == supAuthority) {
                throw new AppException("父权限不存在或已删除！");
            }
            // 限制权限只能为二级
            if (StringUtils.hasText(supAuthority.getSuperId())) {
                throw new AppException("父权限必须是一级权限！");
            }
        } else {
            oldAuthority.setSuperId(null);
        }

        // 设置更新字段
        oldAuthority.setDescription(authority.getDescription());
        oldAuthority.setName(authority.getName());
        oldAuthority.setMenuUrl(authority.getMenuUrl());
        oldAuthority.setSuperId(authority.getSuperId());
        oldAuthority.setStatus(authority.getStatus());
        oldAuthority.setType(authority.getType());
        oldAuthority.setCode(authority.getCode());
        oldAuthority.setIcon(authority.getIcon());
        queryFactory.update(qAuthority)
                .populate(oldAuthority)
                .where(qAuthority.authorityId.eq(authority.getAuthorityId()))
                .execute();

        // 如果排序为空，则排在最后
        if (authority.getSorter() == null) {
            Integer sorter = queryFactory.select(qAuthority.sorter.max())
                    .from(qAuthority)
                    .fetchOne();
            queryFactory.update(qAuthority)
                    .set(qAuthority.sorter, sorter == null ? 1 : sorter + 1)
                    .where(qAuthority.authorityId.eq(authority.getAuthorityId()))
                    .execute();
        } else {
            // 找出平级的权限
            List<Authority> authorities;
            if (StringUtils.hasText(authority.getSuperId())) {
                authorities = getSubAuthority(authority.getSuperId());
            } else {
                authorities = getParentAuthority();
            }
            // 移除自己并添加到第1位
            authorities.removeIf(auth -> auth.getAuthorityId()
                    .equals(authority.getAuthorityId()));
            authorities.add(0, authority);
            // 重新排序并更新
            authorities.sort(Comparator.comparing(Authority::getSorter));
            int sorter = 1;
            SQLUpdateClause update = queryFactory.update(qAuthority);
            for (Authority auth : authorities) {
                update.set(qAuthority.sorter, sorter++)
                        .where(qAuthority.authorityId.eq(auth.getAuthorityId()))
                        .addBatch();
            }
            update.execute();
        }

        return oldAuthority;
    }

    /**
     * 获所有取父权限。
     */
    @Override
    public List<Authority> getParentAuthority() {
        return queryFactory.selectFrom(qAuthority)
                .where(qAuthority.status.eq(1))
                .where(qAuthority.superId.isNull())
                .orderBy(qAuthority.sorter.asc())
                .fetch();
    }

    /**
     * 获取所有子权限
     */
    @Override
    public List<Authority> getSubAuthority(String superId) {
        if (!StringUtils.hasText(superId)) {
            throw new AppException("父权限ID不能为空！");
        }
        return queryFactory.selectFrom(qAuthority)
                .where(qAuthority.superId.eq(superId))
                .where(qAuthority.status.eq(1))
                .orderBy(qAuthority.sorter.asc())
                .fetch();
    }

    @Override
    public List<Authority> getAllAuthorityTree() {
        // 查询所有权限
        List<Authority> authorities = getParentAuthority();
        // 逐个查询子权限菜单
        for (Authority authority : authorities) {
            authority.setSubAuthorities(getSubAuthority(authority.getAuthorityId()));
        }
        return authorities;
    }

    /**
     * 根据名称和URL查询权限并分页。
     */
    @Override
    public Page<Authority> queryAuthorityPage(Paging param, String name, String description) {
        QAuthority SuperAuthority = new QAuthority("SA");
        // 查询所有权限
        SQLQuery<Authority> query = queryFactory.select(
                QueryHelper.allToBean(Authority.class,
                        qAuthority, SuperAuthority.name.as("superName")))
                .from(qAuthority).leftJoin(SuperAuthority)
                .on(qAuthority.superId.eq(SuperAuthority.authorityId))
                .orderBy(qAuthority.sorter.asc());
        // 添加条件限制
        if (StringUtils.hasText(name)) {
            query.where(qAuthority.name.contains(name));
        }
        if (StringUtils.hasText(description)) {
            query.where(qAuthority.description.contains(description));
        }
        // 获取分页结果
        return QueryHelper.queryPage(param, query);
    }

}
